<template>
  <div class="app-container flex flex-sub"
    style="background: none; height: 100%; padding: 1rem">
    <div class="flex"
      style="width: 380px; height: 100%">
      <el-card shadow="never"
        class="box-card flex-sub">
        <treeselect placeholder="选择网格"
          :options="gridTreeDataList"
          :default-expand-level="Infinity"
          style="width: 100%"
          @select="onSelect"
          :value="selectedGrid.guid">
          <div slot="value-label"
            slot-scope="{ node }">
            {{ node.raw.fullPathText }}
          </div>
        </treeselect>

        <div class="device-info"
          :style="{
            height: contentHeight + 'px',
          }">
          <div v-for="(item, index) in deviceGroupList"
            :key="index"
            style="margin-bottom: 15px">
            <div class="device-type">
              <i class="el-icon-caret-bottom"
                v-if="item.expandAll"
                @click="item.expandAll = !item.expandAll"></i>
              <i class="el-icon-caret-right"
                v-if="!item.expandAll"
                @click="item.expandAll = !item.expandAll"></i>
              {{ item.deviceTypeStr }}列表
            </div>
            <div v-if="item.expandAll">
              <div style="padding: 5px 10px">
                <el-input size="mini"
                  placeholder="请输入设备名"
                  v-model="item.inputKey"
                  :clearable="true"
                  @input="onInputKeyChange(index)"></el-input>
              </div>
              <div v-for="(item1, index1) in item.deviceList"
                :key="index1"
                class="device-type-item"
                @click="clickDevice(item1, item)">
                <span :style="{
                  color:
                    selectedDevice.deviceCode == item1.deviceCode
                      ? '#0067FF'
                      : null,
                }">
                  {{ item1.deviceName }}</span>
              </div>
              <div v-if="item.deviceList.length == 0"
                style="margin-left: 20px">
                无设备数据。
              </div>
            </div>
          </div>
        </div>
      </el-card>
    </div>
    <div class="flex flex-sub box-b">
      <template v-if="planeImgUrl == ''">
        <el-card shadow="never"
          class="box-card flex-sub">
          <div class="empty">该区域尚未上传平面图。</div>
        </el-card>
      </template>
      <template v-else>
        <div style="display: flex">
          <div class="div-legend">
            <div style="flex: 1"
              v-for="(item, i) in legendList"
              :key="i">
              <span class="legend"
                :style="{ color: item.color }">●</span>{{ item.label }}
            </div>
          </div>
          <div class="div-legend"
            style="justify-content: center; flex: 1">
            <el-button type="text"
              @click="toResetCanvas"
              style="margin-top: -8px">重置图纸</el-button>
          </div>
        </div>

        <div :style="{
          height: contentHeight - 30 + 'px',
        }"
          class="box-right"
          id="card">
          <canvas id="canvas"
            style="width: 100%; height: 100%"></canvas>
        </div>

        <div class="info-popper"
          :style="{
            top: dialogPointY + 'px',
            left: dialogPointX + 'px',
          }"
          v-if="isShowInfoPopover">
          <div style="margin-top: 10px">
            <template v-if="selectedDevice.type == '采集设备'">
              <div class="info-item">
                <span
                  style="color: #525e8c">设备名称：</span>{{ selectedDevice.deviceName }}
              </div>
              <div class="info-item">
                <span
                  style="color: #525e8c">设备编码：</span>{{ selectedDevice.deviceCode }}
              </div>
              <div class="info-item">
                <span style="color: #525e8c">设备类型：</span>{{
                  selectedDevice.type == '监控设备'
                  ? '监控设备'
                  : selectedDevice.deviceTypeStr
                }}
              </div>
              <div>
                <span style="color: #525e8c">设备状态：</span><span :style="{
                  color:
                    deviceRunningStateStr[selectedDevice.deviceRunningState],
                }">{{ selectedDevice.deviceRunningState }}</span>
              </div>
            </template>
            <template v-else>
              <div @click="playVideo(selectedDevice.streamUrl)">
                <iframe :src="selectedDevice.streamUrl"
                  height="150px"
                  width="100%"
                  style="pointer-events: none"
                  frameborder="0"
                  allowfullscreen
                  allow="autoplay; fullscreen; microphone;"></iframe>
              </div>
            </template>
          </div>
          <div class="close">
            <i class="el-icon-close close-icon"
              @click="closePopover"></i>
          </div>
          <div class="info-popper-arrow"></div>
        </div>

        <el-dialog :visible.sync="isEnlarge"
          width="90%"
          top="0"
          @close="isEnlarge = false"
          :show-close="false"
          :style="{ height: contentHeight + 100 + 'px' }"
          :modal="false">
          <div class="enlarge-window">
            <span
              style="color: #7c9fbd; font-size: 15px; flex: 1">视频名称：{{ selectedDevice.deviceName }}</span>
            <span style="flex: 1; display: flex; justify-content: center">
              {{ date | datefmt('YYYY-MM-DD HH:mm:ss') }}</span>
            <span style="display: flex">
              <i class="el-icon-circle-close"
                style="font-weight: bold; cursor: pointer"
                @click="closeEnlargeWindow"></i></span>
          </div>
          <div>
            <iframe :src="srcUrl"
              frameborder="0"
              style="width: 100%; height: 100%"
              :style="{
                height: contentHeight - 120 + 'px',
              }"
              allowfullscreen
              allow="autoplay; fullscreen; microphone;"></iframe>
          </div>
        </el-dialog>
      </template>
    </div>
  </div>
</template>
<script>
import deviceManageApi from '@/api/device-manage'
import GridManageApi from '@/api/grid-manage'
import { fabric } from 'fabric'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'

export default {
  name: 'SpaceView',
  components: {
    Treeselect,
  },
  data () {
    return {
      contentHeight: 0,

      deviceImgUrl: require('@/assets/acquisitionDevice.png'),
      cameraImgUrl: require('@/assets/cameraDevice1.png'),

      canvasWidth: 0,
      canvasHeight: 0,
      canvasObj: null,

      firstDialogPointX: 0,
      firstDialogPointY: 0,
      dialogPointX: 0,
      dialogPointY: 0,

      gridTreeDataList: [],
      selectedGrid: {},

      deviceDictionaries: [],
      deviceList: [],
      cameraList: [],
      deviceGroupList: [],
      selectedDevice: {},

      legendList: [
        {
          label: '报警',
          color: '#F44343',
        },
        {
          label: '故障',
          color: '#FF6200',
        },
        {
          label: '正常',
          color: '#40E361',
        },
        {
          label: '启动',
          color: '#2A7BFF',
        },
        {
          label: '离线',
          color: '#ABB1B9',
        },
        {
          label: '隔离',
          color: 'rgb(104 106 108)',
        },
      ],

      planeImgUrl: '',
      planeImgElement: null,

      isShowInfoPopover: false,

      deviceRunningStateStr: {
        报警: '#F44343',
        故障: '#FF6200',
        正常: '#40E361',
        启动: '#2A7BFF',
        离线: '#ABB1B9',
        隔离: 'rgb(104 106 108)',
        反馈: '#13c2c2',
      },
      srcUrl: '',
      isEnlarge: false,

      date: new Date(),
    }
  },
  created () {
    let clientHeight = 0
    if (
      document.body.scrollHeight === window.screen.height &&
      document.body.scrollWidth === window.screen.width
    ) {
      clientHeight = window.screen.height - 5 // 网页可见区域高
    } else {
      clientHeight = document.body.clientHeight - 5 // 网页可见区域高
    }
    this.contentHeight = clientHeight - 220
  },
  mounted () {
    this.getGridTree()
    this.getDictValueAttr()
  },
  methods: {


    getGridTree () {
      GridManageApi.getGridTree()
        .then((ret) => {
          this.gridTreeDataList = ret.data.data.rows
          if (this.gridTreeDataList.length != 0) {
            this.selectedGrid = this.gridTreeDataList[0]
          }
        })
        .catch(() => {
          this.gridTreeDataList = []
        })
    },

    getDictValueAttr () {
      const data = {
        fieldName: 'collect_type',
        tableName: 't_equipment_collect',
      }
      deviceManageApi
        .getDictValueAttr(data)
        .then((ret) => {
          this.deviceDictionaries = ret.data.dictValue

          this.getList2DPoint()
        })
        .catch(() => {
          this.getList2DPoint()
        })
    },

    onSelect (node) {
      this.selectedGrid = node
      this.closePopover()
      this.closeEnlargeWindow()
      this.getList2DPoint()
    },
    getList2DPoint () {
      const groupList = [
        {
          deviceTypeStr: '采集设备',
          deviceList: [],
          deviceList_copy: [],
          inputKey: '',
          expandAll: true,
        },
        {
          deviceTypeStr: '监控设备',
          deviceList: [],
          deviceList_copy: [],
          inputKey: '',
          expandAll: true,
        },
      ]
      const P1 = GridManageApi.getList2DPoint(this.selectedGrid.guid)
      const P2 = GridManageApi.getListCamera2DPoint(this.selectedGrid.guid)

      Promise.all([P1, P2]).then((res) => {
        this.deviceList = []
        this.cameraList = []

        res[0].data.forEach((ele) => {
          if (ele.pointX && ele.pointY && ele.pointX != 0 && ele.pointY != 0) {
            this.deviceList.push(ele)
          }
        })
        res[1].data.forEach((ele) => {
          if (ele.pointX && ele.pointY && ele.pointX != 0 && ele.pointY != 0) {
            this.cameraList.push(ele)
          }
        })

        this.deviceList.forEach((ele, idx) => {
          this.deviceDictionaries.forEach((ele1) => {
            if (ele.deviceType == ele1.dictValue) {
              ele.deviceTypeStr = ele1.dictText
            }
          })
        })

        groupList.forEach((ele) => {
          this.deviceList.forEach((item) => {
            if (ele.deviceTypeStr == '采集设备') {
              ele.deviceList.push(item)
              ele.deviceList_copy.push(item)
            }
          })

          this.cameraList.forEach((item) => {
            if (ele.deviceTypeStr == '监控设备') {
              ele.deviceList.push(item)
              ele.deviceList_copy.push(item)
            }
          })
        })

        this.deviceGroupList = groupList

        this.getPlaneImgUrl()
      })
    },
    onInputKeyChange (idx) {
      const item = this.deviceGroupList[idx]
      if (item.inputKey == '') {
        item.deviceList = item.deviceList_copy
      } else {
        item.deviceList = item.deviceList_copy.filter(
          (p) => p.deviceName.indexOf(item.inputKey) > -1
        )
      }
    },

    clickDevice (data1, data) {
      this.toResetCanvas()

      this.selectedDevice = data1
      this.selectedDevice.type = data.deviceTypeStr

      this.toShowInfoPopover(
        this.selectedDevice.pointX,
        this.selectedDevice.pointY
      )
    },

    getPlaneImgUrl () {
      GridManageApi.getGridDetail(this.selectedGrid.guid).then((ret) => {
        this.planeImgUrl = ret.data.files ? ret.data.files.url : ''
        if (this.planeImgUrl && this.planeImgUrl != '') {
          this.drawCanvas()
        }
      })
    },

    onSelectedDeviceChange (idx) {
      this.deviceGroupList[idx].deviceList.forEach((ele) => {
        if (ele.deviceCode == this.selectedDeviceCode) {
          this.selectedDeviceObj = ele
          this.selectedDeviceObj.type = this.deviceGroupList[idx].deviceTypeStr
        }
      })
    },

    // 画图
    drawCanvas () {
      this.planeImgElement = document.createElement('img')
      this.planeImgElement.src = this.planeImgUrl
      this.planeImgElement.onload = () => {
        const a = document.getElementById('card')
        a.oncontextmenu = function () {
          // return false
          const _event = window.event || e //事件对象
          if (_event.preventDefault) {
            _event.preventDefault() //标准格式
          } else {
            _event.returnValue = false //IE格式
          }
        }

        const cw = this.planeImgElement.width
        const ch = this.planeImgElement.height
        this.canvasWidth = cw
        this.canvasHeight = ch

        if (this.canvasObj != null) {
          let obj = this.canvasObj.getObjects()
          obj.forEach((ele) => {
            this.canvasObj.remove(ele)
          })
        } else {
          this.canvasObj = new fabric.Canvas('canvas', {
            // preserveObjectStacking: false, // 禁⽌选中图层时⾃定置于顶部
            fireRightClick: true, // 启用右键，button的数字为3
            stopContextMenu: true, // 禁止默认右键菜单
            selection: false, // 是否应在画布上启用对象选择
          })
        }

        this.canvasObj.setWidth(this.canvasWidth) //设置画布宽度
        this.canvasObj.setHeight(this.canvasHeight) //设置画布⾼度
        this.canvasObj.setBackgroundImage(
          this.planeImgUrl,
          this.canvasObj.renderAll.bind(this.canvasObj),
          {
            scaleY: 1,
            scaleX: 1,
          }
        )

        this.toResetCanvas()
        this.canvasObj.requestRenderAll()

        // 滚轮缩放
        this.canvasObj.on('mouse:wheel', (opt) => {
          const delta = opt.e.deltaY // 滚轮，向上滚一下是 -100，向下滚一下是 100
          let zoom = this.canvasObj.getZoom() // 获取画布当前缩放值
          zoom *= 0.999 ** delta
          if (zoom > 20) zoom = 20
          if (zoom < 0.01) zoom = 0.01

          // 以左上角为原点
          // this.canvas.setZoom(zoom)

          // 以鼠标所在位置为原点缩放
          this.canvasObj.zoomToPoint(
            {
              // 关键点
              x: opt.e.offsetX,
              y: opt.e.offsetY,
            },
            zoom
          )
          opt.e.preventDefault()
          opt.e.stopPropagation()

          this.isShowInfoPopover = false
        })
        let isDragging = false
        let lastPosX = 0
        let lastPosY = 0
        // alt+按下鼠标事件
        this.canvasObj.on('mouse:down', (opt) => {
          var evt = opt.e
          if (evt.altKey === true) {
            isDragging = true
            lastPosX = evt.clientX
            lastPosY = evt.clientY
          }
        })

        // 移动鼠标事件
        this.canvasObj.on('mouse:move', (opt) => {
          if (isDragging) {
            var e = opt.e
            var vpt = this.canvasObj.viewportTransform
            vpt[4] += e.clientX - lastPosX
            vpt[5] += e.clientY - lastPosY
            this.canvasObj.requestRenderAll()
            lastPosX = e.clientX
            lastPosY = e.clientY
          }
        })

        // 松开鼠标事件
        this.canvasObj.on('mouse:up', (opt) => {
          this.canvasObj.setViewportTransform(this.canvasObj.viewportTransform)
          if (isDragging) {
            // const vpt = this.canvasObj.viewportTransform
            // this.dialogPointX = this.firstDialogPointX + vpt[4]
            // this.dialogPointY = this.firstDialogPointY + vpt[5]

            this.isShowInfoPopover = false
          }

          isDragging = false
        })

        this.deviceGroupList.forEach((ele) => {
          ele.deviceList.forEach((item) => {
            this.toAddDevicePoint(item, ele.deviceTypeStr)
          })
        })
      }
    },

    // 绑定设备点位
    toAddDevicePoint (item, type) {
      const img = new Image()
      const imgWidth = 32
      if (type == '监控设备') {
        img.src = this.cameraImgUrl
      } else {
        if (item.deviceRunningState == '报警') {
          img.src = require('@/assets/alarmDevice.png')
        } else if (item.deviceRunningState == '故障') {
          img.src = require('@/assets/faultDevice.png')
        } else {
          img.src = this.deviceImgUrl
        }
      }
      img.style.width = imgWidth + 'px'
      img.style.height = imgWidth + 'px'
      img.onload = () => {
        const devicePointImg = new fabric.Image(img, {
          left: item.pointX - imgWidth / 2,
          top: item.pointY - imgWidth / 2,
          width: imgWidth,
          height: imgWidth,
          id: item.deviceCode,
          type: type,
          data: item,
        })
        devicePointImg.hasBorders = false //“hasBorders” 和“hasControls”属性来控制对象的边框和顶点的可见性。
        devicePointImg.hasControls = false
        devicePointImg.hoverCursor = 'pointer' // 鼠标移动到对象上的样式（默认值：move）
        devicePointImg.moveCursor = 'pointer' // 对象拖动时的鼠标样式（默认值：move）
        devicePointImg.lockMovementX = true
        devicePointImg.lockMovementY = true
        this.canvasObj.add(devicePointImg)

        devicePointImg.on('mousedown', (event) => {
          // 鼠标右键点击平面图中的任一设备，弹出该设备信息
          if (event.button == 1) {
            this.selectedDevice = event.target.data
            this.selectedDevice.type = event.target.type

            let offX = 0
            if (event.transform.offsetX < 16) {
              offX = event.pointer.x + (16 - event.transform.offsetX.toFixed(0))
            } else if (event.transform.offsetX > 16) {
              offX = event.pointer.x - (event.transform.offsetX.toFixed(0) - 16)
            }

            let offY = 0
            if (event.transform.offsetY < 16) {
              offY = event.pointer.y + (16 - event.transform.offsetY.toFixed(0))
            } else if (event.transform.offsetY > 16) {
              offY = event.pointer.y - (event.transform.offsetY.toFixed(0) - 16)
            }
            setTimeout(() => {
              this.toShowInfoPopover(offX, offY)
            }, 100)
          }
        })
      }
    },
    toShowInfoPopover (x, y) {
      this.firstDialogPointX = x - 125
      this.firstDialogPointY = y - 165

      this.dialogPointX = this.firstDialogPointX
      this.dialogPointY = this.firstDialogPointY

      this.isShowInfoPopover = true
    },

    // 重置图纸
    toResetCanvas () {
      if (this.canvasObj != null) {
        this.canvasObj.setViewportTransform([1, 0, 0, 1, 0, 0])

        this.dialogPointX = this.selectedDevice.pointX - 125
        this.dialogPointY = this.selectedDevice.pointY - 165
      }
    },

    closePopover () {
      this.isShowInfoPopover = false
      this.selectedDevice = {}
    },

    playVideo (url) {
      this.srcUrl = url
      this.isEnlarge = true
      this.isShowInfoPopover = false
    },
    closeEnlargeWindow () {
      this.isEnlarge = false
      this.selectedDevice = {}
    },
  },
}
</script>

<style lang="scss" scoped>
@import '../../../../styles/part-custom';

.content {
  display: flex;
  margin-top: 10px;
}

.box-left {
  width: 350px;
  height: 100%;
}

.box-right {
  flex: 1;
  height: 100;
  margin-left: 10px;
  padding-top: 0px;
  // overflow: auto;
  overflow: hidden;
  position: relative;
}

.device-info {
  width: 100%;
  overflow: auto;
  margin-top: 10px;

  .device-type {
    color: #686464;
    font-size: 15px;
    font-weight: bold;
    cursor: pointer;
  }

  .device-type-item {
    padding: 8px 15px 0px 30px;
    display: block;
    cursor: pointer;
  }
}

.device-info::-webkit-scrollbar-track-piece {
  background: #d3dce6;
}

.device-info::-webkit-scrollbar {
  width: 6px;
  height: 8px;
}

.device-info::-webkit-scrollbar-thumb {
  background: #99a9bf;
  border-radius: 20px;
}

.box-b {
  margin-left: 0.5rem;
  width: calc(100% - 390px);
  height: 100%;
  display: flex;
  flex-direction: column;
  position: relative;
}

.div-legend {
  display: flex;
  width: 450px;
  height: 20px;
  margin: -5px 5px 5px 5px;
}

.legend {
  font-size: 16px;
  margin-right: 2px;
}

.empty {
  width: 100%;
  height: 100%;
  text-align: center;
  margin-top: 20%;
  font-size: 20px;
}

.info-popper {
  width: 260px;
  height: 170px;
  transform-origin: center bottom;
  // z-index: 2150;
  position: absolute;
  top: 163px;
  left: 294px;

  background: #fff;
  min-width: 150px;
  border-radius: 4px;
  border: 1px solid #ebeef5;
  padding: 5px;

  color: #606266;
  line-height: 1.4;
  text-align: justify;
  font-size: 14px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  word-break: break-all;
  // margin-bottom: 12px;

  .icon-error {
    position: absolute;
    right: -5px;
    top: -8px;
    font-size: 22px;
    cursor: pointer;
  }

  .info-item {
    margin-bottom: 12px;
  }

  .info-popper-arrow {
    position: absolute;
    display: block;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
    border-width: 6px;
    filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03));
    left: 85.5px;
    bottom: -6px;
    left: 50%;
    margin-right: 3px;
    border-top-color: #ebeef5;
    border-bottom-width: 0;
  }

  .info-popper-arrow::after {
    bottom: 1px;
    content: ' ';
    border-width: 6px;
    position: absolute;
    display: block;
    width: 0;
    height: 0;
    border-color: transparent;
    border-style: solid;
    margin-left: -6px;
    border-top-color: #fff;
    border-bottom-width: 0;
  }

  .close {
    position: absolute;
    right: 3px;
    top: 0px;
  }

  .close-icon {
    font-weight: bold;
    font-size: 18px;
    cursor: pointer;
  }
}

.enlarge-window {
  margin-bottom: 20px;
  display: flex;
  font-size: 22px;
  color: white;
}

/*form样式-----------------------------------------------------------------------------------------------------*/
/deep/.el-form-item--small.el-form-item {
  margin: 6px 0;
}

/deep/.el-form-item__label {
  text-align: right;
  vertical-align: middle;
  float: left;
  font-size: 14px;
  line-height: 32px;
  padding: 0 4px 0 0;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  color: #000000d9;
  font-weight: normal;
}

/deep/ .el-form-item__label::after {
  content: ':';
  position: relative;
  top: -0.5px;
  margin: 0 8px 0 2px;
}

/deep/.el-form-item--small .el-form-item__error {
  padding-top: 2px;
  margin-bottom: -6px;
  position: relative;
}

/deep/.el-page-header__title {
  color: #303133;
}

/deep/.el-page-header__left .el-icon-back {
  color: #303133;
}

/deep/.el-dialog__wrapper {
  position: relative;
}

/deep/.el-dialog__header {
  border-bottom-width: 0px;
  background: black;
}

/deep/.el-dialog {
  background: black;
  box-shadow: 0 0 0px #5592f3;
}
</style>
